/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "core/shader_line.h"
#include "矩阵.h"

#include "线性代数/矢量计算.h"

#include "面/Surface.h"
#include "面/Mesh.h"

#include <vulkan/vulkan.h>




struct S_Mesh操作 {
	S_Surface*	m_Mesh;


	S_Mesh操作(S_Surface* s);

	void f_重置网格(S_Surface* s);

	void f_Add(const S_Mesh操作* mesh, const Mat44f* mat);
	void f_fill网格(const std::vector<vec3> xyz, const std::vector<vec3> normal, const std::vector<uvec4_8> color, const std::vector<uint32> index, const std::vector<vec2> texcoord, uint8 纹理坐标层数);
	void f_add顶点(const vec3& xyz, const vec3& normal, const uvec4_8& color, const vec2* texcoord, uint8 纹理坐标层数);
	//void f_add三角形(const vector<ivec3> index, uint32 iNum);
	void f_add三角形(const ivec3& index);


	void f_set顶点(uint32 index, const vec3& xyz);
	void f_set法线(uint32 index, const vec3& xyz);
	void f_set颜色(uint32 index, const vec3& xyz);
	void f_set纹理坐标(uint32 index, const vec2& xyz);




	uint32		f_get顶点数量();
	const vec3*	f_get顶点();
	vec3*		f_Map顶点();
	void		f_UnMap_顶点();




	uint32			f_get索引数量();
	const uint32*	f_get索引();
	uint32*			f_Map索引();
	void			f_UnMap_索引();


	void f_pick();

	void f_toGPU();




};







struct S_Mesh_CUDA : public S_Mesh {

	void f_AddMesh(const S_Mesh& m);

	uint32_t f_GetNumVertices() const { return uint32_t(m_positions.size()); }
	uint32_t f_GetNumFaces() const { return uint32_t(m_indices.size()) / 3; }

	virtual S_结构对象指针	f_get顶点() { return (S_结构对象指针)&m_positions; };
	virtual S_结构对象指针	f_get法线() { return (S_结构对象指针)&m_normals; };
	virtual S_结构对象指针	f_get索引() { return (S_结构对象指针)&m_indices; };

	virtual	void f_get顶点(S_结构对象指针 data);
	virtual	void f_get法线(S_结构对象指针 data);
	virtual	void f_get索引(S_结构对象指针 data);



	virtual void f_fill顶点(const std::vector<vec3>& xyz);
	virtual void f_fill法线(const std::vector<vec3>& normal);
	virtual void f_fill索引(const std::vector<uint32>& index);
	virtual void f_fill颜色(const std::vector<uvec4_8>& color);
	virtual void f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层);


	virtual void f_fill顶点(const vec3* xyz, uint32 num);
	virtual void f_fill法线(const vec3* normal, uint32 num);
	//virtual void f_fill索引(const uint32* index, uint32 num);
	virtual void f_fillUV(const vec2* index, uint32 num);




	virtual	uint32			f_get顶点数量() { return m_positions.size(); }


	void f_DuplicateVertex(uint32_t i);

	void f_CalculateNormals();
	//void f_Transform(const Matrix44& m);
	void f_Normalize(float s = 1.0f);	// scale so bounds in any dimension equals s and lower bound = (0,0,0)

	void f_getBounds(Vec3& minExtents, Vec3& maxExtents) const;

	std::vector<Point3>		m_positions;
	std::vector<Vec3>		m_normals;
	std::vector<Vec3>		m_texcoords[2];
	std::vector<Colour>		m_colours;

	std::vector<uint32_t> m_indices;


	//void		f_合并(std::vector<S_Mesh*>& meshs);
};











struct S_Mesh_CPU : public S_Mesh {

	void f_AddMesh(const S_Mesh& m);

	virtual void f_fill顶点(const std::vector<vec3>& xyz);
	virtual void f_fill法线(const std::vector<vec3>& normal);
	virtual void f_fill索引(const std::vector<uint32>& index);
	virtual void f_fill颜色(const std::vector<uvec4_8>& color);
	virtual void f_fillUV(const std::vector<vec2>& texcoord, uint8 纹理层);


	virtual void f_fill顶点(const vec3* xyz, uint32 num);
	virtual void f_fill法线(const vec3* normal, uint32 num);
	//virtual void f_fill索引(const uint32* index, uint32 num);
	virtual void f_fillUV(const vec2* index, uint32 num);


	virtual void f_填充顶点数据(const std::vector<S_VN>& data);
	virtual void f_填充顶点数据(const std::vector<S_VC>& data);

	virtual uint32 f_填充顶点数据(uint16 bitSize, uint64 num, void* data);
	virtual uint32 f_填充索引数据(uint16 bitSize, uint64 num, void* data);

	virtual	uint32			f_get顶点数量() { return m_positions.size(); }


	void f_get顶点(std::vector<vec3>& vert) const;
	void f_get法线(std::vector<vec3>& normal) const;
	void f_get索引(std::vector<uint32>& index) const;
	void f_get颜色(std::vector<vec4>& index) const;


	void f_Clear();
	void f_Clear索引();

	void f_getBounds(Vec3& minExtents, Vec3& maxExtents) const;

	std::vector<vec3>		m_positions;
	std::vector<vec3>		m_normals;
	std::vector<vec2>		m_texcoords[2];
	//std::vector<Colour>		m_colours;
	std::vector<uint32>		m_indices;


	E_序列map	f_map顶点() { 
		uint32 num = m_positions.size();
		if (*m_顶点配置Flags == E_顶点组合标志::e_坐标_法线) {
			num /= 2;
		}
		return { m_positions.data(), num };
	}
	E_序列map	f_map索引() { return { m_indices.data(), m_indices.size() }; }
	//void		f_unmap顶点();
	//void		f_unmap索引();

	//void		f_合并(std::vector<S_Mesh*>& meshs);
};








struct S_VKMesh板载缓存 : public S_Mesh {
	uint32		m_VertNum;

	//S_板载缓存* m_顶点;
	//S_板载缓存* m_法线;
	//S_板载缓存* m_UV1;
	VkAccelerationStructureKHR m_光追加速结构;


	S_VKMesh板载缓存(S_设备环境& ctx);
	S_VKMesh板载缓存(S_VKMesh板载缓存* ctx);
	S_VKMesh板载缓存();
	~S_VKMesh板载缓存();
	

	void	f_拷贝实例(const S_Mesh* mesh);


	void	f_fill顶点(const vec3* xyz, uint32 num);
	void	f_fill法线(const vec3* normal, uint32 num);
	void	f_fillUV(const vec2* uv, uint32 num, uint8 纹理层);
	void	f_fill颜色(const std::vector<S_RGBA8UI>& c);
	uint32	f_fillUV索引数据(uint16 bitSize, uint32 num, const void* data);

	void	f_fillUV(const std::vector<vec2>& uv1, uint8 纹理层) ;
	void	f_fill权重(const float32* w, uint32 num);
	void	f_fill骨骼ID(const uint32* bid, uint32 num);
	void	f_fill骨骼属性(const S_骨骼属性& 骨骼属性);
	

	void	f_填充顶点数据(const std::vector<S_VN>& data);
	void	f_填充顶点数据(const std::vector<S_VC>& data);
	uint32	f_填充顶点数据(uint16 bitSize, uint64 num, void* data);
	uint32	f_填充索引数据(uint16 bitSize, uint64 num, void* data);
	

	void	f_重置顶点数量(uint64 num);
	void	f_Clear();
	void	f_Clear索引();




	void f_get顶点(std::vector<vec3>& vert) const;
	void f_get法线(std::vector<vec3>& normal) const;
	void f_get索引(std::vector<uint32>& index) const;
	void f_get颜色(std::vector<vec4>& index) const;


	//void f_set顶点(const S_UI32Array* index, const S_Vec3Array* xyz);
	//void f_set法线(const S_UI32Array* index, const S_Vec3Array* normal);


	//void f_resize顶点(uint32 num);
	//void f_计算包围盒();


	uint32	f_get顶点数量();
	uint32	f_get索引数量();

	void		f_绘制(S_渲染参数& 渲染参数);
	
};



void f_mesh_顶点类型切换(S_Mesh* 目标, const S_Mesh* 源);


VkAccelerationStructureKHR& f_mesh_get加速结构(S_VKMesh板载缓存* me);




